﻿
using EasyNet.Componets.Core.Utils;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using ZXing;
using ZXing.Common;

namespace EasyNet.Componets.Images
{
    
    public static class EasyNetImage
    {
        #region 生成随机码
        /// <summary>
        /// 该方法是将生成的随机码写入图像文件
        /// </summary>
        /// <param name="len">随机码长度</param>
        /// <param name="code">随机码</param>
        public static MemoryStream CreateRandomCode(int len, out string code)
        {
            code = RandomUtil.GetLetterOrDigit(len);
            return CreateRandomCode(code);
        }

        /// <summary>
        /// 该方法是将生成的随机码写入图像文件
        /// </summary>
        /// <param name="len">随机码长度</param>
        /// <param name="code">随机码</param>
        public static MemoryStream CreateRandomCode(string code)
        {
            Bitmap Img = null;
            Graphics g = null;
            MemoryStream ms = null;
            System.Random random = new Random();
            //验证码颜色集合
            Color[] c = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple };
            //验证码字体集合
            string[] fonts = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" };
            //定义图像的大小，生成图像的实例
            Img = new Bitmap(100, 25);
            //从Img对象生成新的Graphics对象 
            g = Graphics.FromImage(Img);
            //背景设为白色
            g.Clear(Color.White);
            //在随机位置画背景点
            for (int i = 0; i < 100; i++)
            {
                int x = random.Next(Img.Width);
                int y = random.Next(Img.Height);
                g.DrawRectangle(new Pen(Color.LightGray, 0), x, y, 1, 1);
            }
            //验证码绘制在g中
            for (int i = 0; i < code.Length; i++)
            {
                int cindex = random.Next(7);//随机颜色索引值
                int findex = random.Next(5);//随机字体索引值
                Font f = new System.Drawing.Font(fonts[findex], 14, System.Drawing.FontStyle.Bold);//字体
                Brush b = new System.Drawing.SolidBrush(c[cindex]);//颜色
                int ii = 4;
                if ((i + 1) % 2 == 0)//控制验证码不在同一高度
                {
                    ii = 2;
                }
                g.DrawString(code.Substring(i, 1), f, b, 3 + (i * 20), ii);//绘制一个验证字符
            }
            ms = new MemoryStream();//生成内存流对象
            Img.Save(ms, ImageFormat.Jpeg);//将此图像以jpg图像文件的格式保存到流中
            //回收资源
            g.Dispose();
            Img.Dispose();
            return ms;
        }
        #endregion

        #region 二维码
        public static string CreateQrCode(string url, int width, int height)
        {
            BitMatrix bitMatrix;
            bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, width, height);
            BarcodeWriter bw = new BarcodeWriter();

            MemoryStream ms = new MemoryStream();
            var bitmap = bw.Write(bitMatrix);
            bitmap.Save(ms, ImageFormat.Png);

            byte[] arr = new byte[ms.Length];
            ms.Position = 0;
            ms.Read(arr, 0, (int)ms.Length);
            ms.Close();
            string strbaser64 = Convert.ToBase64String(arr);
            strbaser64 = string.Format("data:image/{1};base64,{0}", strbaser64, ImageFormat.Png.ToString());
            return strbaser64;
        }
        #endregion

        #region 检查图片格式
        /// <summary>
        /// 检查图片是否为指定的图片格式
        /// </summary>
        /// <param name="image">图片对象</param>
        /// <param name="imageformat">图片格式</param>
        /// <returns>等于指定的图片格式返回true,否则为false</returns>
        public static bool CheckFormat(Image image, ImageFormat imageformat)
        {
            bool flag = false;
            if ((image != null) && image.RawFormat.Equals(imageformat))
            {
                flag = true;
            }
            return flag;
        }

        /// <summary>
        /// 检查图片是否为指定的图片格式
        /// </summary>
        /// <param name="stream">数据流</param>
        /// <param name="imageformat">图片格式</param>
        /// <returns>等于指定的图片格式返回true,否则为false</returns>
        public static bool CheckFormat(Stream stream, ImageFormat imageformat)
        {
            return CheckFormat(Image.FromStream(stream), imageformat);
        }

        /// <summary>
        /// 检查图片是否为指定的图片格式
        /// </summary>
        /// <param name="fileName">图片地址</param>
        /// <param name="imageformat">图片格式</param>
        /// <returns>等于指定的图片格式返回true,否则为false</returns>
        public static bool CheckFormat(string fileName, ImageFormat imageformat)
        {
            return CheckFormat(Image.FromFile(fileName), imageformat);
        }

        #endregion

        #region 检查图片的深度
        /// <summary>
        /// 检查图片的深度
        /// </summary>
        /// <param name="image">图片对象</param>
        /// <param name="pixel">深度</param>
        /// <returns>等于指定的深度返回true,否则为false</returns>
        public static bool CheckPixel(Image image, int pixel)
        {
            bool flag = false;
            if ((image != null) && (Image.GetPixelFormatSize(image.PixelFormat) == pixel))
            {
                flag = true;
            }
            return flag;
        }

        /// <summary>
        /// 检查图片的深度
        /// </summary>
        /// <param name="stream">数据流</param>
        /// <param name="pixel">深度</param>
        /// <returns>等于指定的深度返回true,否则为false</returns>
        public static bool CheckPixel(Stream stream, int pixel)
        {
            return CheckPixel(Image.FromStream(stream), pixel);
        }

        /// <summary>
        /// 检查图片的深度
        /// </summary>
        /// <param name="fileName">图片地址</param>
        /// <param name="pixel">深度</param>
        /// <returns>等于指定的深度返回true,否则为false</returns>
        public static bool CheckPixel(string fileName, int pixel)
        {
            return CheckPixel(Image.FromFile(fileName), pixel);
        }
        #endregion

        #region 获取图片深度
        /// <summary>
        /// 获取图片的深度
        /// </summary>
        /// <param name="image">图片对象</param>
        /// <returns>返回指定图片的深度</returns>
        public static int GetPixel(Image image)
        {
            return Image.GetPixelFormatSize(image.PixelFormat);
        }

        /// <summary>
        /// 获取图片的深度
        /// </summary>
        /// <param name="stream">数据流</param>
        /// <returns>返回指定图片的深度</returns>
        public static int GetPixel(Stream stream)
        {
            return GetPixel(Image.FromStream(stream));
        }

        /// <summary>
        /// 获取图片的深度
        /// </summary>
        /// <param name="fileName">图片地址</param>
        /// <returns>返回指定图片的深度</returns>
        public static int GetPixel(string fileName)
        {
            return GetPixel(Image.FromFile(fileName));
        }
        #endregion

        #region 保存图片
        /// <summary>
        /// 保存图片对象到指定的位置
        /// </summary>
        /// <param name="image">要存储的图片对象</param>
        /// <param name="savePath">图片要保存的位置（绝对地址）</param>
        private static void Save(Image image, string savePath)
        {
            if ((!string.IsNullOrEmpty(savePath) && savePath.Contains(@"\")))
            {
                var jmgFormat = GetImageFormat(savePath);//获取文件格式
                image.Save(savePath, jmgFormat);
            }
        }

        /// <summary>
        /// 获取文件格式
        /// </summary>
        /// <param name="savePath"></param>
        /// <returns></returns>
        private static ImageFormat GetImageFormat(string savePath)
        {
            string str = Path.GetExtension(savePath).ToLower();
            ImageFormat jpeg = ImageFormat.Jpeg;
            switch (str)
            {
                case ".bmp":
                    jpeg = ImageFormat.Bmp;
                    break;

                case ".emf":
                    jpeg = ImageFormat.Emf;
                    break;

                case ".exif":
                    jpeg = ImageFormat.Exif;
                    break;

                case ".gif":
                    jpeg = ImageFormat.Gif;
                    break;

                case ".icon":
                    jpeg = ImageFormat.Icon;
                    break;

                case ".png":
                    jpeg = ImageFormat.Png;
                    break;

                case ".tiff":
                    jpeg = ImageFormat.Tiff;
                    break;

                case ".wmf":
                    jpeg = ImageFormat.Wmf;
                    break;

                default:
                    jpeg = ImageFormat.Jpeg;
                    break;
            }
            return jpeg;
        }
        #endregion

        #region 缩略图
        /// <summary>
        /// 从指定的原图片，生成缩略图
        /// </summary>
        /// <param name="image">原图片</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <returns>返回生成的缩略图对象</returns>
        public static Image Thumbnail(Image image, int width, int height)
        {
            return Thumbnail(image, string.Empty, width, height);
        }

        /// <summary>
        /// 从指定的位置加载图片，生成并保存缩略图
        /// </summary>
        /// <param name="sourcePath">原图片的地址,如果文件没有有效的图像格式，或者如果 GDI+ 不支持文件的像素格式，则此方法将引发 OutOfMemoryException 异常</param>
        /// <param name="thumbnailPath">缩略图保存地址，不设置则不保存图片到物理磁盘</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <returns>返回生成的缩略图对象</returns>
        public static Image Thumbnail(string sourcePath, string thumbnailPath, int width, int height)
        {
            if (string.IsNullOrEmpty(sourcePath) || !File.Exists(sourcePath))
            {
                throw new ArgumentException("原图片的地址不能为空或文件不存在");
            }
            return Thumbnail(Image.FromFile(sourcePath), thumbnailPath, width, height);
        }

        /// <summary>  
        /// 无损压缩图片  
        /// </summary>  
        /// <param name="sourcePath">原图片</param>  
        /// <param name="thumbnailPath">压缩后保存位置</param>  
        /// <param name="width">宽度</param>  
        /// <param name="height">高度</param>  
        /// <param name="compression">压缩质量(数字越小压缩率越高) 1-100</param>  
        /// <returns></returns>  
        public static Image Thumbnail(string sourcePath, string thumbnailPath, int width, int height, int compression)
        {
            if (string.IsNullOrEmpty(sourcePath) || !File.Exists(sourcePath))
            {
                throw new ArgumentException("原图片的地址不能为空或文件不存在");
            }
            return Thumbnail(Image.FromFile(sourcePath), thumbnailPath, width, height, compression);
        }


        /// <summary>
        /// 从指定的原图片，生成缩略图
        /// </summary>
        /// <param name="image">原图片</param>
        /// <param name="thumbnailPath">缩略图保存地址，不设置则不保存图片到物理磁盘</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="compression">无损压缩比例：1-100</param>
        /// <returns>返回生成的缩略图对象</returns>
        public static Image Thumbnail(Image image, string thumbnailPath, int width, int height)
        {
            if (image == null)
            {
                throw new ArgumentNullException("原图片不能为null");
            }
            if ((width <= 0) || (height <= 0))
            {
                throw new ArgumentException("缩略图宽度或高度不能小于或等于零");
            }
            image = image.GetThumbnailImage(width, height, null, new IntPtr());
            Save(image, thumbnailPath);
            return image;
        }

        /// <summary>
        /// 生成压缩图片
        /// </summary>
        /// <param name="image"></param>
        /// <param name="savePath"></param>
        /// <param name="compression"></param>
        /// <returns></returns>
        public static Image Thumbnail(Image image, string thumbnailPath, int compression)
        {
            EncoderParameters ep = new EncoderParameters(1);
            ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, compression);//设置压缩的比例1-100
            ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
            var jmgFormat = GetImageFormat(thumbnailPath);//获取文件格式
            ImageCodecInfo jpegICIinfo = arrayICI.FirstOrDefault(t => t.FormatID == jmgFormat.Guid);

            if (jpegICIinfo != null)
            {
                image.Save(thumbnailPath, jpegICIinfo, ep);
            }
            else
            {
                image.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            return image;
        }

        /// <summary>
        /// 生成压缩图片
        /// </summary>
        /// <param name="image"></param>
        /// <param name="savePath"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="compression"></param>
        /// <returns></returns>
        public static Image Thumbnail(Image image, string thumbnailPath, int width, int height, int compression)
        {
            using (Bitmap dstimg = new Bitmap(width, height))//图片压缩质量
            {
                //从Bitmap创建一个System.Drawing.Graphics对象，用来绘制高质量的缩小图。
                using (Graphics gr = Graphics.FromImage(dstimg))
                {
                    //把原始图像绘制成上面所设置宽高的缩小图
                    Rectangle rectDestination = new Rectangle(0, 0, width, height);
                    gr.Clear(Color.WhiteSmoke);
                    gr.CompositingQuality = CompositingQuality.HighQuality;
                    gr.SmoothingMode = SmoothingMode.HighQuality;
                    gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    gr.DrawImage(image, rectDestination, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);

                    return Thumbnail(dstimg, thumbnailPath, compression);
                }
            }
        }
        #endregion

        #region 水印图片

        /// <summary>
        /// 从指定的图片，生成并保存水印图片
        /// </summary>
        /// <param name="image">原图片</param>
        /// <param name="mark">添加的水印文字</param>
        /// <param name="position">添加位置</param>
        /// <returns>返回生成的水印图对象</returns>
        public static Image Watermark(Image image, string mark, WatermarkPosition position)
        {
            return Watermark(image, string.Empty, mark, position);
        }

        /// <summary>
        /// 从指定的图片，生成并保存水印图片
        /// </summary>
        /// <param name="image">原图片</param>
        /// <param name="watermarkPath">水印图片保存地址，不设置则不保存至磁盘</param>
        /// <param name="mark">添加的水印文字</param>
        /// <param name="position">添加位置</param>
        /// <returns>返回生成的水印图对象</returns>
        public static Image Watermark(Image image, string watermarkPath, string mark, WatermarkPosition position)
        {
            if (image == null)
            {
                throw new ArgumentNullException("原图片不能为null");
            }
            if (string.IsNullOrEmpty(mark))
            {
                throw new ArgumentException("水印文字不能为空");
            }
            using (Graphics graphics = Graphics.FromImage(image))
            {
                graphics.DrawImage(image, 0, 0, image.Width, image.Height);
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                using (Font font = new Font("Arial", 10f, FontStyle.Italic | FontStyle.Bold))
                {
                    using (Brush brush = new SolidBrush(Color.White))
                    {
                        SizeF ef = graphics.MeasureString(mark, font);
                        float x = 0f;
                        float y = 0f;
                        switch (position)
                        {
                            case WatermarkPosition.Bottom_left:
                                x = 10f;
                                y = (image.Height - ef.Height) - 10f;
                                break;

                            case WatermarkPosition.Top_left:
                                x = 10f;
                                y = 10f;
                                break;

                            case WatermarkPosition.Top_right:
                                x = (image.Width - ef.Width) - 10f;
                                y = 10f;
                                break;

                            case WatermarkPosition.Center:
                                x = (((float)image.Width) / 2f) - (ef.Width / 2f);
                                y = (((float)image.Height) / 2f) - (ef.Height / 2f);
                                break;

                            default:
                                x = (image.Width - ef.Width) - 10f;
                                y = (image.Height - ef.Height) - 10f;
                                break;
                        }
                        graphics.DrawString(mark, font, brush, x, y);
                        Save(image, watermarkPath);
                    }
                }
                return image;
            }
        }

        /// <summary>
        /// 从指定的图片，生成并保存水印图片
        /// </summary>
        /// <param name="sourcePath">原图片的地址,如果文件没有有效的图像格式，或者如果 GDI+ 不支持文件的像素格式，则此方法将引发 OutOfMemoryException 异常</param>
        /// <param name="watermarkPath">水印图片保存地址,不设置则，不保存图片到物理磁盘</param>
        /// <param name="mark">添加的水印文字</param>
        /// <param name="position">添加位置</param>
        /// <returns>返回生成的水印图对象</returns>
        public static Image Watermark(string sourcePath, string watermarkPath, string mark, WatermarkPosition position)
        {
            if (string.IsNullOrEmpty(sourcePath) || !File.Exists(sourcePath))
            {
                throw new ArgumentException("原图片的地址不能为空或文件不存在");
            }
            return Watermark(Image.FromFile(sourcePath), watermarkPath, mark, position);
        }
        #endregion

        #region ToBase64String
        /// <summary>
        ///  将图片文件转换成 Base64String
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns></returns>
        public static string ToBase64String(string fileName)
        {
            using (var ms = new MemoryStream())
            {
                Bitmap bmp = new Bitmap(fileName);
                var imageFormat = GetImageFormat(fileName);//图片格式
                bmp.Save(ms, imageFormat);
                byte[] bytes = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(bytes, 0, (int)ms.Length);
                string base64String = Convert.ToBase64String(bytes);
                base64String = string.Format("data:image/{1};base64,{0}", base64String, ImageFormat.Png.ToString());
                ms.Close();
                bmp.Dispose();
                ms.Dispose();
                return base64String;
            }
        }
        #endregion

        #region ToMemoryStream

        public static MemoryStream ToMemoryStream(string file, ImageFormat format)
        {
            MemoryStream ms = new MemoryStream();
            var img = Image.FromFile(file);
            img.Save(ms, format);

            ms.Flush();
            ms.Seek(0, SeekOrigin.Begin);
            return ms;
        }

        public static MemoryStream ToDefaultMemoryStream(string file)
        {
            return ToMemoryStream(file, ImageFormat.Png);
        }
        #endregion

    }
}
